package org.jeecg.business.webapp.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.jeecg.business.webapp.service.CustemService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.community.entity.XyParkBill;
import org.jeecg.community.entity.XyParkBillHouse;
import org.jeecg.community.service.IXyParkBillHouseService;
import org.jeecg.community.service.IXyParkBillService;
import org.jeecg.modules.online.cgform.entity.OnlCgformHead;
import org.jeecg.modules.online.cgform.mapper.OnlCgformFieldMapper;
import org.jeecg.modules.online.cgform.service.IOnlCgformFieldService;
import org.jeecg.modules.online.cgform.service.IOnlCgformHeadService;
import org.jeecg.modules.online.cgform.util.SqlSymbolUtil;
import org.jeecg.modules.system.service.SnRuleService;
import org.jeecg.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@RestController
@RequestMapping("/custom")
public class CustemController {
	
	@Value("${jeecg.wx.hr.agentId}")
	private Integer agentId;
	
	@Autowired
	private CustemService custemService;
	
	@Autowired
    private IOnlCgformHeadService onlCgformHeadService;
	
	@Autowired
    private IOnlCgformFieldService fieldService;
	
	@Autowired
	private IXyParkBillService xyParkBillService;
	
	@Autowired
	private SnRuleService snRuleService;
	
	@Autowired
	private IXyParkBillHouseService xyParkBillHouseService;
	
	@GetMapping(value = "/backfile/{code}")
	public Result<?> queryPageList(@PathVariable("code") String code) {
		custemService.reBackFile(code);
		return Result.OK();
	}
	
	@PostMapping(value = "/patroltask/status/{taskCode}")
	public Result<?> patroltaskStatus(@PathVariable("taskCode") String taskCode) {
		OnlCgformFieldMapper onlCgformFieldMapper = SpringContextUtils.getBean(OnlCgformFieldMapper.class);
		String countSql = "select count(1) from xy_park_patrol_taskinfo where task_code = '"+ taskCode +"' and patrol_status = '1'";
		Integer count = onlCgformFieldMapper.queryCountBySql(countSql);
		String updateSql;
		if(count>0){
			updateSql = "update xy_park_patrol_task set task_status = '2' where task_code = '"+ taskCode +"'";
		}else{
			updateSql = "update xy_park_patrol_task set task_status = '3' where task_code = '"+ taskCode +"'";
		}
		onlCgformFieldMapper.editFormData(updateSql);
		return Result.OK();
	}
	
	@ApiOperation(value = "合同管理-账单生成", notes = "合同管理-账单生成")
	@GetMapping(value = "/generateBill")
	@Transactional(readOnly = false)
	public Result<?> generateBill(@ApiParam(name="formDataId", value="表单数据Id", required = true) @RequestParam("formDataId") String formDataId,
			@ApiParam(name="mainTable", value="合同主表", required = true) @RequestParam("mainTable") String mainTable,
			@ApiParam(name="costTable", value="费项子表", required = true) @RequestParam("costTable") String costTable,
			@ApiParam(name="houseTable", value="房间子表", required = true) @RequestParam("houseTable") String houseTable,
    		HttpServletRequest request){
		OnlCgformHead head = onlCgformHeadService.getOne(new QueryWrapper<OnlCgformHead>().eq("table_name", mainTable));
    	if (head == null) {
            return Result.error("合同实体不存在");
        }
    	Map<String, Object> map;
		map = this.fieldService.queryBpmData(head.getId(), head.getTableName(), formDataId);
		map = SqlSymbolUtil.getValueType(map);
		
		Map<String, Object> params = new HashMap<>();
		params.put("contract_code", map.get("contract_code"));
		
		OnlCgformHead headPayinfo = onlCgformHeadService.getOne(new QueryWrapper<OnlCgformHead>().eq("table_name", costTable));
    	if (headPayinfo == null) {
            return Result.error("费项实体不存在");
        }
		
		Map<String, Object> payinfo = fieldService.queryAutolistPage(headPayinfo.getTableName(), headPayinfo.getId(), params, null);
		
		OnlCgformHead headDetail = onlCgformHeadService.getOne(new QueryWrapper<OnlCgformHead>().eq("table_name", houseTable));
    	if (headDetail == null) {
            return Result.error("明细实体不存在");
        }
		Map<String, Object> detail = fieldService.queryAutolistPage(headDetail.getTableName(), headDetail.getId(), params, null);
		
		
		
		if(payinfo.get("records") != null){
			List<Map<String, Object>> payRecords = (List<Map<String, Object>>) payinfo.get("records");
			int count = xyParkBillService.count(new QueryWrapper<XyParkBill>().eq("contract_code", map.get("contract_code")));
			if(count == 0){
				for(Map<String, Object> fee : (List<Map<String, Object>>) payinfo.get("records")){
					XyParkBill bill = new XyParkBill();
					bill.setAmount((BigDecimal) fee.get("price"));
					bill.setDueDate((Date) fee.get("collection_date"));
					bill.setStartDate((Date) fee.get("start_date"));
					bill.setEndDate((Date) fee.get("end_date"));
					bill.setBillStatus("3");
					bill.setContractCode((String) map.get("contract_code"));
					bill.setBillSource("2");
					bill.setCostType((String) fee.get("cost_type"));
					bill.setOwnerCode((String) map.get("owner_code"));
					bill.setCustomerAccount((String) map.get("park_number"));
					bill.setBillCode(snRuleService.execute("XY-SK-${YYYY}${MM}-###", null) + "");
					bill.setBillType("1");
					xyParkBillService.save(bill);
					if(detail.get("records") != null){
						List<Map<String, Object>> detailRecords = (List<Map<String, Object>>) detail.get("records");
						for(Map<String, Object> house : detailRecords){
							XyParkBillHouse billHouse = new XyParkBillHouse();
							billHouse.setBillCode(bill.getBillCode());
							billHouse.setBuildingArea((BigDecimal) house.get("building_area"));
							billHouse.setBuildingName((String) house.get("building_name"));
							billHouse.setFloor((String) house.get("floor"));
							billHouse.setHouseCode((String) house.get("house_code"));
							billHouse.setProjectName((String) house.get("project_name"));
							billHouse.setPropertyArea((BigDecimal) house.get("property_area"));
							xyParkBillHouseService.save(billHouse);
						}
					}
				}
			}else if(count > 0){
				return Result.error("合同已存在账单！");
			}else{
				return Result.error("合同无账单可生成！");
			}
		}
		
		return Result.OK("账单生成成功!", null);
	}
	
	@ApiOperation(value = "抄表-获取上期读数", notes = "抄表-获取上期读数")
	@GetMapping(value = "/getMeterRead")
	public Result<?> getMeterRead(@ApiParam(name="deviceCode", value="设备ID", required = true) @RequestParam("deviceCode") String deviceCode) {
		String countSql = "Select count(1) from xy_park_meterreadingrecord where device_code = '"+deviceCode+"' and billing_status = '1'";
		OnlCgformFieldMapper onlCgformFieldMapper = SpringContextUtils.getBean(OnlCgformFieldMapper.class);
		Integer count = onlCgformFieldMapper.queryCountBySql(countSql);
		if(count != 1){
			return Result.error("设备历史记录有误");
		}
		String selectSql = "Select * from xy_park_meterreadingrecord where device_code = '"+deviceCode+"' order by create_time desc limit 1";
		Map<String, Object> result = onlCgformFieldMapper.queryFormData(selectSql);
		if("billing_status".equals(result.get("2"))){
			return Result.error("设备历史记录有误");
		}
		
		return Result.OK(result);
	}
	
	@GetMapping(value = "/testPage")
	public Result<?> testPage() throws WxErrorException{
		return Result.OK();
	}
	
	@ApiOperation(value = "抄表-获取流水", notes = "抄表-获取流水")
	@GetMapping(value = "/getAccountFlow")
	public Result<?> getAccountFlow(@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
			   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
			   @RequestParam(name="account_code", required = false) String account_code,
			   @RequestParam(name="house_code", required = false) String house_code,
			   @RequestParam(name="payment_type", required = false) String payment_type,
			   @RequestParam(name="trading_time_begin", required = false) String trading_time_begin,
			   @RequestParam(name="trading_time_end", required = false) String trading_time_end,
			   HttpServletRequest req) {
		OnlCgformFieldMapper onlCgformFieldMapper = SpringContextUtils.getBean(OnlCgformFieldMapper.class);
		StringBuffer where = new StringBuffer("where 1=1");
		if(account_code != null){
			where.append("and account_code = '" + account_code +"'");
		}
		if(house_code != null){
			where.append("and house_code = '" + house_code +"'");
		}
		if(payment_type != null){
			where.append("and payment_type = '" + payment_type +"'");
		}
		if(trading_time_begin != null){
			where.append("and (trading_time between '" + trading_time_begin +"' and '" + trading_time_end + "') ");
		}
		String selectSql = "Select (SELECT ifnull(sum(check_amount),0) FROM  xy_park_account_flow_bill_ship s WHERE s.account_code = f.account_code) matched_amout,f.*,d.device_code from xy_park_accounting_flow f left join (select dh.house_code,de.device_code,de.device_sort from xy_park_devicehouse dh left join xy_park_device de on de.device_code = dh.device_code) d on f.listing_no = d.house_code and f.payment_type = d.device_sort "+ where.toString() +" order by f.create_time desc";
		IPage<Map<String, Object>> page = onlCgformFieldMapper.selectPageBySql(new Page<Map<String, Object>>(pageNo,pageSize), selectSql);
		return Result.OK(page);
	}
	
	@ApiOperation(value = "抄表-获取账单", notes = "抄表-获取账单")
	@GetMapping(value = "/getMeterBill")
	public Result<?> getMeterBill(@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
			   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
			   @RequestParam(name="bill_code", required = false) String bill_code,
			   @RequestParam(name="device_code", required = false) String device_code,
			   @RequestParam(name="clear_status", required = false) String clear_status,
			   @RequestParam(name="due_date_begin", required = false) String due_date_begin,
			   @RequestParam(name="due_date_end", required = false) String due_date_end,
			   HttpServletRequest req) {
		OnlCgformFieldMapper onlCgformFieldMapper = SpringContextUtils.getBean(OnlCgformFieldMapper.class);
		StringBuffer where = new StringBuffer("where 1=1");
		if(bill_code != null){
			where.append("and bill_code = '" + bill_code +"'");
		}
		if(device_code != null){
			where.append("and device_code = '" + device_code +"'");
		}
		if(clear_status != null){
			where.append("and clear_status = '" + clear_status +"'");
		}
		if(due_date_begin != null){
			where.append("and (due_date between '" + due_date_begin +"' and '" + due_date_end + "') ");
		}
		String selectSql = "Select (SELECT ifnull(sum(check_amount),0) FROM  xy_park_account_flow_bill_ship s WHERE s.bill_code = b.bill_code) matched_amout,b.* from xy_park_meterreadingbill b "+ where.toString() +" order by b.create_time desc";
		IPage<Map<String, Object>> page = onlCgformFieldMapper.selectPageBySql(new Page<Map<String, Object>>(pageNo,pageSize), selectSql);
		return Result.OK(page);
	}
	
	@ApiOperation(value = "抄表-获取已匹配账单", notes = "抄表-获取已匹配账单")
	@GetMapping(value = "/getBillList")
	public Result<?> getBillList(@RequestParam(name="account_code") String account_code) {
		OnlCgformFieldMapper onlCgformFieldMapper = SpringContextUtils.getBean(OnlCgformFieldMapper.class);
		String selectSql = "SELECT b.bill_code,b.cost_type,b.cost_name,b.bill_amount,b.meter_diff,b.record_code,b.device_code,s.check_amount FROM xy_park_account_flow_bill_ship s LEFT JOIN xy_park_meterreadingbill b ON s.bill_code = b.bill_code WHERE s.account_code = '"+ account_code +"'";
		List<Map<String, Object>> result = onlCgformFieldMapper.queryListBySql(selectSql);
		return Result.OK(result);
	}
	
	@ApiOperation(value = "抄表-获取已匹配流水", notes = "抄表-获取已匹配流水")
	@GetMapping(value = "/getFlowList")
	public Result<?> getFlowList(@RequestParam(name="bill_code") String bill_code) {
		OnlCgformFieldMapper onlCgformFieldMapper = SpringContextUtils.getBean(OnlCgformFieldMapper.class);
		String selectSql = "SELECT f.*,s.check_amount FROM xy_park_account_flow_bill_ship s LEFT JOIN xy_park_accounting_flow f ON s.account_code = f.account_code WHERE s.bill_code = '"+ bill_code +"'";
		List<Map<String, Object>> result = onlCgformFieldMapper.queryListBySql(selectSql);
		return Result.OK(result);
	}
	
	@ApiOperation(value = "抄表-自动匹配", notes = "抄表-自动匹配")
	@GetMapping(value = "/autoAmount")
	public Result<List<Map<String, Object>>> autoAmount(@RequestParam(name = "account_code", required = true) String account_code) {
		OnlCgformFieldMapper onlCgformFieldMapper = SpringContextUtils.getBean(OnlCgformFieldMapper.class);
		String selectAcountSql = "Select f.*,d.device_code from xy_park_accounting_flow f left join (select dh.house_code,de.device_code,de.device_sort from xy_park_devicehouse dh left join xy_park_device de on de.device_code = dh.device_code) d on f.listing_no = d.house_code and f.payment_type = d.device_sort where f.account_code = '" + account_code + "'";
		Map<String, Object> acount = onlCgformFieldMapper.queryFormData(selectAcountSql);
		
		String sumAmountByAccountSql = "SELECT ifnull(sum(check_amount),0) amount FROM  xy_park_account_flow_bill_ship WHERE account_code = '" + account_code + "'";
		Map<String, Object> amountMap = onlCgformFieldMapper.queryFormData(sumAmountByAccountSql);
		BigDecimal checkAmount = new BigDecimal(amountMap.get("amount").toString());
		//剩余待匹配金额
		BigDecimal amount = new BigDecimal(acount.get("amount").toString()).subtract(checkAmount);
		
		String selectBillSql = "SELECT"
				+ "	b.*,t.cost_name, IFNULL(a.check_amount, 0) sum_check_amount,"
				+ "	("
				+ "		b.bill_amount - IFNULL(a.check_amount, 0)"
				+ "	) surplus_amount "
				+ "FROM "
				+ "	xy_park_meterreadingbill b "
				+ "LEFT JOIN ( "
				+ "	SELECT "
				+ "		bill_code,"
				+ "		IFNULL(SUM(check_amount), 0) check_amount "
				+ "	FROM "
				+ "		xy_park_account_flow_bill_ship "
				+ "	GROUP BY"
				+ "		bill_code"
				+ ") a ON a.bill_code = b.bill_code "
				+ "LEFT JOIN xy_park_cost_type t on b.cost_type = t.cost_type "
				+ "WHERE "
				+ "	("
				+ "		b.clear_status <> '3' "
				+ "		OR b.clear_status IS NULL "
				+ "	)"
				+ "AND bill_status = '3' "
				+ "AND device_code = '" + acount.get("device_code") +"'"
				+ "ORDER BY"
				+ "	b.create_time DESC";
		List<Map<String, Object>> bills = onlCgformFieldMapper.queryListBySql(selectBillSql);
		List<Map<String, Object>> result = new ArrayList<>();
		for(Map<String, Object> billVo : bills){
			amount = amount.subtract(new BigDecimal(billVo.get("surplus_amount").toString()));
			if(amount.compareTo(BigDecimal.ZERO) <= 0){
				billVo.put("plan_amount",amount.add(new BigDecimal(billVo.get("surplus_amount").toString())));
				result.add(billVo);
				break;
			}else{
				billVo.put("plan_amount",new BigDecimal(billVo.get("surplus_amount").toString()));
				result.add(billVo);
			}
		}
		return Result.OK(result);
	}
	
	@ApiOperation(value = "抄表-添加账单匹配", notes = "抄表-添加账单匹配")
	@PostMapping(value = "/addAmount")
	public Result<?> addAmount(@RequestBody List<Map<String, Object>> ships){
		OnlCgformFieldMapper onlCgformFieldMapper = SpringContextUtils.getBean(OnlCgformFieldMapper.class);
		
		String username = getLoginUser() == null?"":getLoginUser().getUsername();
		
		StringBuffer insertSql = new StringBuffer("insert into xy_park_account_flow_bill_ship (id, create_by, create_time, account_code, bill_code, check_amount) values");
		for(Map<String, Object> ship : ships){
			String uuid = UUID.randomUUID().toString();
			insertSql.append("(");
			insertSql.append("'" + uuid + "'");
			insertSql.append(",'" + username + "'");
			insertSql.append(",NOW()");
			insertSql.append(",'" + ship.get("account_code") + "'");
			insertSql.append(",'" + ship.get("bill_code") + "'");
			insertSql.append("," + ship.get("check_amount") + "");
			insertSql.append("),");
		}
		insertSql.setLength(insertSql.length() -1 );
		onlCgformFieldMapper.saveFormData(insertSql.toString());
		
		for(Map<String, Object> ship : ships){
			String billSql = "select * from xy_park_meterreadingbill where bill_code = '" + ship.get("bill_code") + "'";
			Map<String, Object> bill = onlCgformFieldMapper.queryFormData(billSql);
			String amountSql = "SELECT ifnull(sum(check_amount),0) amount from xy_park_account_flow_bill_ship WHERE bill_code = '" + ship.get("bill_code") + "'";
			BigDecimal amount = new BigDecimal(onlCgformFieldMapper.queryFormData(amountSql).get("amount").toString());
			String updateBillSql = "";
			if(new BigDecimal(bill.get("bill_amount").toString()).compareTo(amount) <= 0){
				updateBillSql = "update xy_park_meterreadingbill set clear_status = '3' where bill_code = '" + ship.get("bill_code") + "'";
			}else{
				updateBillSql = "update xy_park_meterreadingbill set clear_status = '2' where bill_code = '" + ship.get("bill_code") + "'";
			}
			onlCgformFieldMapper.editFormData(updateBillSql);
		}
		return Result.OK("添加成功！", ships);
	}
	
	private LoginUser getLoginUser() {
		LoginUser sysUser = null;
		try {
			sysUser = SecurityUtils.getSubject().getPrincipal() != null ? (LoginUser) SecurityUtils.getSubject().getPrincipal() : null;
		} catch (Exception e) {
			//e.printStackTrace();
			sysUser = null;
		}
		return sysUser;
	}
}
